import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  WebView,
  Image,
  ListView,
  TouchableHighlight,
  Navigator,
  Modal,
  Dimensions,
  TextInput,
} from 'react-native';

import {
    Container, Header, Content, Footer, Button, Title, Icon, List, ListItem,
    Spinner,
} from 'native-base';

import NetworkInfo from 'react-native-network-info';
import {Copper, CoapMessage} from './Copper';
import SimpleConfig from './SimpleConfig';
import LightControl from './LightControl';
import SocketUtil from './SocketUtil';

export default class MainScreen extends Component {

    TOKEN_DISCOVER_DEVICE = 'DSCV';

    constructor(props)
    {
        super(props);
        this._lights = [];
        this.state = {modalVisible: false, loading: false};

        NetworkInfo.getSSID(ssid => {this.setState({ssid});});
        console.log(SocketUtil);
        this.socketUtil = new SocketUtil();
        this.socketUtil.initSocket(this.onMessage.bind(this), () => {
            this.discoverDevice();
        });
    }

    render() {
        const mainScene =
        <Container>
            <Header>
                <Button transparent> </Button>
                <Title>{this.props.route.title}</Title>
                <Button transparent onPress={() => this.discoverDevice()}>
                    <Icon name='md-refresh' style={{fontSize:22}}/>
                </Button>
                <Button transparent onPress={() => this.setState({modalVisible: true})}>
                    <Icon name = 'ios-add-circle-outline' style={{fontSize:22}}/>
                </Button>
            </Header>
            <Content>
                <Modal
                    visible={this.state.modalVisible}
                    transparent={true}
                    onRequestClose={() => {}}>
                    <View style={{backgroundColor:'rgba(0,0,0,0.5)', height:Dimensions.get('window').height}}>
                        <View style={{margin:10, padding:10, backgroundColor:'white', borderRadius: 5}}>
                            <Text>SSID: {this.state.ssid}</Text>
                            <TextInput placeholder="Enter password"
                                secureTextEntry={true}
                                autoCorrect={false}
                                onChangeText={(password) => this.setState({password})}/>
                            <View style={{flexDirection: 'row', justifyContent: 'flex-end'}}>
                                <View style={{flex:2}}/>
                                <Button bordered small style={{flex:1}} onPress={() => this.setState({modalVisible: false})}>Cancel</Button>
                                <View style={{width:10}}/>
                                <Button bordered small style={{flex:1}} onPress={() => {
                                                this.setState({modalVisible: false});
                                                this.configDevice();
                                            }}>OK</Button>
                            </View>
                        </View>
                    </View>
                </Modal>

                {this.state.loading? <Spinner /> :
                <List dataArray={this._lights}
                    renderRow={(item) =>
                        <ListItem button onPress={() => this.lightControl(item)}>
                            <Icon name='ios-bulb-outline' style={{fontSize: 20, marginRight:10}}/><Text>{item.Name}</Text>
                        </ListItem>
                    }>
                </List>
                }
            </Content>
        </Container>;

        return mainScene;
    }

    componentWillUnmount() {
        if(this.discoverDeviceInterval != undefined) {
            clearInterval(this.discoverDeviceInterval);
        }
    }

    lightControl(light) {
        this.props.navigator.push({title:light.Name, component: LightControl, light: light});
    }

    configDevice(){
        SimpleConfig.configDevice(this.state.ssid, this.state.password, 60000,
            (devices) => {
                console.log('discovered device num:' + devices.length);
                for(var i = 0; i < devices.length; i++) {
                    this.addDevice(devices[i]);
                }
            },
            (error) => {
                console.error(error);
            })
    }

    addDevice(device) {
        var found = false;
        for(var i = 0; i < this._lights.length; i++) {
            if(this._lights[i].MAC === device.MAC) {
                this._lights[i].ipaddr = device.ipaddr;
                this._lights[i].Name = device.Name;
                found = true;
                break;
            }
        }
        if(!found) {
            this._lights.push(device);
        }
        this.setState({loading: true});
        this.setState({loading: false});
    }

    discoverDevice() {
        this.setState({loading: true});

        if(this.discoverDeviceInterval != undefined) {
            clearInterval(this.discoverDeviceInterval);
        }

        let msg = new CoapMessage(Copper.MSG_TYPE_CON, Copper.GET);
        msg.setUri("127.0.0.1", "/deviceDiscovery");
        msg.setUriPort(Copper.DEFAULT_PORT);
        msg.setToken(this.TOKEN_DISCOVER_DEVICE);
        //msg.setPayload(colorString);
        let packet = Copper.serialize(msg);
        console.log("packet", msg.getSummary());

        // Settings for resend
        this.discoverDeviceRetries = 0;
        this.discoverDevicePacket = packet;
        this.discoverDeviceInterval = setInterval(() => {
            this.discoverDeviceRetries++;
            if(this.discoverDeviceRetries > 10) {
                console.log("cancel discover device interval.");
                clearInterval(this.discoverDeviceInterval);
                this.discoverDeviceInterval = undefined;
                this.setState({loading:false});
            }
            else {
                console.log("resend discover device msg");
                this.socketUtil.send('255.255.255.255', Copper.DEFAULT_PORT, this.discoverDevicePacket);
            }
        }, 1000);

        this._lights = [];
        this.socketUtil.send('255.255.255.255', Copper.DEFAULT_PORT, packet);
    }

    onMessage(msg, rinfo){
        console.log('recevied: ' + msg.length);
        var data = Array.from(msg);
        let coapMsg = Copper.parse(data);
        console.log("uri:", coapMsg.getUriPath());
        console.log(coapMsg.getSummary());

        let token = coapMsg.getToken();
        var payload = coapMsg.getPayload();

        if(token !== this.TOKEN_DISCOVER_DEVICE) {
            return;
        }
        if(payload.length != 15) {
            console.warn('Payload length is wrong.');
            return;
        }

        let flag = this.getFlag(payload);
        if(flag !== 'cmpCL') {
            console.warn('Not compare color lights');
            return;
        }

        let mac = this.getMac(payload);
        let ipaddr = this.getIpaddr(payload);

        this.addDevice({Name: mac, IP: ipaddr, MAC: mac});
    }

    getFlag(payload){
        if(payload.length < 5) {
            return undefined;
        }
        let buffer = payload.slice(0, 5);
        return Copper.bytes2data(buffer);
    }

    getMac(payload) {
        if(payload.length < 11) {
            return undefined;
        }

        let buffer = payload.slice(5, 11);
        var mac = '';
        for(var i = 0; i < buffer.length; i++) {
            if(i > 0) {
                mac += ':';
            }
            var hex = buffer[i].toString(16).toUpperCase();
            if(hex.length < 2) {
                hex = '0' + hex;
            }
            mac += hex;
        }
        return mac;
    }

    getIpaddr(payload) {
        if(payload.length < 15) {
            return undefined;
        }

        let buffer = payload.slice(11, 15);
        var ip = '';
        for(var i = 0; i < buffer.length; i++) {
            if(i > 0) {
                ip += '.';
            }
            ip += buffer[i].toString();
        }
        return ip;
    }

}
